package graph.visitors;

import graph.dependencies.IDependency;
import graph.dependencies.ImplementableInterfaceDependency;
import graph.dependencies.MethodInvocationDependency2;
import graph.dependencies.ResponsibilityDependency;
import graph.dependencies.VariableDependency;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.internal.corext.dom.Bindings;


public class DependencyCollector extends ASTVisitor {
	
	private List<IDependency> _dependencies = new LinkedList<IDependency>();
	
	public DependencyCollector() {
		//clearInstances();
	}
	
	public void clearInstances() {
		ImplementableInterfaceDependency.clearClasses();
		MethodInvocationDependency2.clearInstances();
	}
	
	@Override
	public void endVisit(Assignment node) {
		IVariableBinding assignedVariable = Bindings.getAssignedVariable(node);
		if (assignedVariable!=null) {
			System.out.println("Dependency collector>Assignment "+node.toString()+" tells about life of a variable "+assignedVariable.getName());
			super.endVisit(node);
		}
	}
	
	@Override
	public boolean visit(FieldDeclaration node) {
		try {
			System.out.println("Dependency collector>FieldDeclaration "+node.toString()+" type: "+node.getType().resolveBinding().getName());
			for (Iterator fragmentIterator = node.fragments().iterator(); fragmentIterator.hasNext();) {
				Object fragment = fragmentIterator.next();
				System.out.println("Dependency collector>FieldDeclaration:Object "+fragment);
				if (fragment!=null) {
					System.out.println("Dependency collector>FieldDeclaration:node.getType() "+node.getType());
					VariableDeclarationFragment frag = (VariableDeclarationFragment)fragment;
					System.out.println("Dependency collector>FieldDeclaration:frag "+frag);
					_dependencies.add(new VariableDependency(node.getType(), frag));
					System.out.println("Dependency collector>VariableDependency created and added ");
				}
			}
			System.out.println("Dependency collector>Digg in with a super method");
			return super.visit(node);
		} catch (Exception e) {
			System.out.println("DependencyCollector>ERROR: "+e.getMessage());
			return false;
		}
	}
	
	
	@Override
	public boolean visit(VariableDeclarationStatement node) {
		System.out.println("Dependency collector>VariableDeclarationStatement:"+node.toString()+" type="+node.getType().toString());
		for(int i = 0; i < node.fragments().size(); ++i)
        {
			System.out.println("Dependency collector>VariableDeclarationStatement:VariableDeclarationFragment "+i);
            VariableDeclarationFragment frag = (VariableDeclarationFragment)node.fragments().get(i);
            _dependencies.add(new VariableDependency(node.getType(), frag));
        }
		return super.visit(node);
	}
	
	/*@Override
	public boolean visit(VariableDeclarationFragment node) {
		System.out.println("DependencyCollector>VariableDeclarationFragment "+node.toString()+" type="+node.resolveBinding().getType().getQualifiedName());
		return super.visit(node);
	}*/
	
	@Override
	public boolean visit(MethodInvocation node) {
		_dependencies.add(new MethodInvocationDependency2(node));//new MethodInvocationDependency1(node));
		return super.visit(node);
	}
	
	@Override
	public boolean visit(TypeDeclaration node) {
		if (node.isInterface())
			_dependencies.add(new ImplementableInterfaceDependency(node));
		else {
			ImplementableInterfaceDependency.addClass(node);
			_dependencies.add(new ResponsibilityDependency(node));
		}
		return super.visit(node);
	}
	
	public List<IDependency> getDependencies() {
		return _dependencies;
	}
	
}
